<template>
  <div id="index" ref="index">
    <div class="leftContain">
      <div ref="stencilContainer" id="stencilContainer"></div>
    </div>
    <div class="centerContain">
      <div class="header" :style="{'width': width}">
        <el-button type="primary" @click="save">保存</el-button>
        <el-button type="primary" @click="onUndo" :disabled="!canUndo">撤销</el-button>
        <el-button type="primary" @click="onRedo" :disabled="!canRedo">恢复</el-button>
        <el-button type="primary" @click="handlePreviewOperation">预览</el-button>
      </div>
      <div ref="container" id="container" :style="{'width': width}"></div>
    </div>
    <div class="rightContain">
      <RightToolBar
          :svgInfo="selectSvgInfo"
          :tableData="tableData"
          @getRightData="getRightData"
          @addTable="addTable"
      ></RightToolBar>
    </div>
  </div>
</template>


<script>
import { Graph, Shape, Node } from '@antv/x6'
import { Stencil } from '@antv/x6-plugin-stencil'
import { History } from '@antv/x6-plugin-history'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Selection } from '@antv/x6-plugin-selection'
import { Clipboard } from '@antv/x6-plugin-clipboard'
import { Transform } from '@antv/x6-plugin-transform'
import { Snapline } from '@antv/x6-plugin-snapline'
import { register } from '@antv/x6-vue-shape'
import tableNode from '../admin/components/antV-vue-shape/tableNode.vue'
import RightToolBar from '../admin/components/RightToolBar.vue'
import { initAntVNode } from "@/utils/antV-x6"
import { deal } from "@/utils/dealShow";
import axios from "axios";
import Vue from "vue";

register({
  shape: 'table',
  width: 150,
  height: 150,
  component: tableNode,
})

export default {
  components: { RightToolBar },
  data() {
    return {
      stencilData:{},
      containerData:{},
      allData:[],
      //右侧数据
      selectSvgInfo:{},
      tableData: [],
      //
      width:'10.5rem',
      number:0,
      canRedo:false,
      canUndo:false,
      vertex_show:'hidden',
      //节点表，对应图表
      nodeList: [],
    }
  },
  methods: {
    init(){
      //创建画布，并初始化其中配置信息
      this.containerData = new Graph({
        container: document.getElementById('container'),
        autoResize:true,
        grid: true,
        mousewheel:{
          enabled:true,
          zoomAtMousePosition:false,
        },
        connecting: {
          router: 'manhattan',
          connector: {
            name: 'rounded',
            radius: 8
          },
          snap: {
            radius: 20,
          },
          createEdge() {
            return new Shape.Edge({
              attrs: {
                line: {
                  stroke: 'white',
                  strokeDasharray: 5,
                  targetMarker: 'classic',
                  style: {
                    animation: 'ant-line 5s infinite linear',
                  },
                }
              }
            })
          }
        },
        panning: {
          enabled: true,
          modifiers: ['ctrl'],
          eventTypes: ['leftMouseDown'],
        },
      })

      /**
       * 历史记录：主要用于撤回与恢复
       */
      this.containerData.use(
          new History({
            enabled: true,
          }),
      )
      this.containerData.on('history:change', () => {
        this.canRedo = this.containerData.canRedo()
        this.canUndo = this.containerData.canUndo()
      })

      /**
       * 对齐线
       */
      this.containerData.use(
          new Snapline({
            enabled: true,
            sharp: true,
            clean: true, // 避免移动节点时对齐线被频繁添加/移除到 DOM
          }),
      )

      /**
       * 快捷键
       * ctrl+c：复制
       * ctrl+v：粘贴
       * backspace：删除
       */
      this.containerData.use(
          new Clipboard({
            enabled: true,
          }),
      )
      this.containerData.use(
          new Selection({
            enabled:true,
            rubberband: true
          }),
      )
      this.containerData.use(
          new Keyboard({
            enabled: true,
            global: true,
          }),
      )
      //大小变化
      this.containerData.use(
          new Transform({
            resizing:{
              enabled: true,
              minWidth: 30,
              minHeight: 30,
              maxWidth: 200,
              maxHeight: 200
            },
            rotating:{
              enabled: true,
              grid: 15,
            }
          }),
      )

      this.bindKey();


      //监听事件
      this.onListen()

      /**
       * 通过stencilData实现组件拖拽
       */
      this.containerData.centerContent()
      this.stencilData = new Stencil({
        title: '组件',
        target: this.containerData,
        search: true,   //搜索
        collapsable: true,
        stencilGraphWidth: 200,
        stencilGraphHeight: 0,
        groups: [
          {
            name: 'group1',
            title: '第一组',
            columns: 2,
            columnWidth: 80,
            rowHeight: 55,
          },
          {
            name: 'group2',
            title: '第二组',
            columns: 2,
            columnWidth: 80,
            rowHeight: 55,
          },
        ],
      })
      this.$refs.stencilContainer.appendChild(this.stencilData.container)
      //导入数据
      this.loadData()

      this.containerData.fromJSON(JSON.parse(localStorage.getItem("svgInfo")))
    },
    //撤销与恢复
    onUndo(){
      this.containerData.undo()
    },
    onRedo(){
      this.containerData.redo()
    },
    //控制连接桩的显影
    showPorts(ports, show){
      for (let i = 0, len = ports.length; i < len; i += 1) {
        ports[i].style.visibility = show ? 'visible' : 'hidden'
      }
    },
    //画布监听事件
    onListen(){
      /**
       * 控制锚点以及元素的显影
       * 通过监听事件实现：
       * mouseenter：鼠标进入 mouseleave：鼠标离开   控制锚点显影
       * contextmenu：鼠标右击   控制元素显影
       * contextmenu：鼠标右击   控制元素显影
       */
      this.containerData.on('node:mouseenter', () => {
        let container = this.$refs.container
        let ports = container.getElementsByClassName('x6-port')
        this.showPorts(ports, true)
      })
      this.containerData.on('node:mouseleave', () => {
        let container = this.$refs.container
        let ports = container.getElementsByClassName('x6-port')
        this.showPorts(ports, false)
      })
      this.containerData.on('node:added',(node)=>{
        node.node.setData({
          name: '',
          guid: '',
        })
        if(node.node.store.data.shape === 'svgNode'){
          let tempBool = true
          this.nodeList.forEach((item) => {
            if(item.id === node.node.id){
              tempBool = false
            }
          })
          if(tempBool === true){
            this.nodeList.push(node.node)
          }
          for (let i = 0; i < node.node.store.data.ports.items.length; i++) {
            node.node.store.data.ports.items[i].id = node.node.store.data.id + '-' + node.node.store.data.ports.items[i].id
          }
        }
        else if(node.node.store.data.shape === 'table'){
          this.nodeList.forEach((item) => {
            if(item.store.data.tableId === node.node.id){
              this.containerData.removeNode(node.node)
            }
          })
        }
      })
      this.containerData.on('node:click',({node}) => {
        console.log(node)
        this.selectSvgInfo = node
        this.tableData = node.data.tableData
      })

      this.containerData.on('node:contextmenu',({cell})=>{
        deal(this.containerData.toJSON(),cell,this.containerData,cell.store.data.count)
      })


      this.containerData.on('edge:mouseenter', ({ cell }) => {
        this.containerData.toggleHistory(false)
        if (!cell.hasTool('vertices')){
          cell.addTools({name: 'vertices'})
        }
        if (!cell.hasTool('button-remove')) {
          cell.addTools('button-remove')
        }
        this.containerData.toggleHistory(true)
      })
      this.containerData.on('edge:mouseleave', ({ cell }) => {
        this.containerData.toggleHistory(false)
        if (cell.hasTool('vertices')) {
          cell.removeTool('vertices')
        }
        if (cell.hasTool('button-remove')) {
          cell.removeTool('button-remove')
        }
        this.containerData.toggleHistory(true)
      })
      this.containerData.on('edge:contextmenu',({edge})=>{
        this.selectSvgInfo = edge
      })

      this.containerData.on('history:change', () => {
        this.canRedo = this.containerData.canRedo()
        this.canUndo = this.containerData.canUndo()
      })

      this.containerData.on('cell:selected',({cell})=>{
        if (this.containerData.findViewByCell(cell).container.firstChild.tagName === 'rect'){
          this.containerData.findViewByCell(cell).container.firstChild.style.visibility = 'visible'
        }
      })
      this.containerData.on('cell:unselected',({cell})=>{
        if (this.containerData.findViewByCell(cell) !== null){
          if (this.containerData.findViewByCell(cell).container.firstChild.tagName === 'rect'){
            this.containerData.findViewByCell(cell).container.firstChild.style.visibility = 'hidden'
          }
        }
      })
      this.containerData.on('cell:click',({cell})=>{
        if (this.containerData.findViewByCell(cell).container.firstChild.tagName === 'rect'){
          this.containerData.findViewByCell(cell).container.firstChild.style.visibility = 'hidden'
        }
      })

    },
    //画布绑定的快捷键
    bindKey(){
      this.containerData.bindKey('ctrl+c', () => {
        const cells = this.containerData.getSelectedCells()
        if (cells.length) {
          this.containerData.copy(cells)
        }
        return false
      })
      this.containerData.bindKey('ctrl+v', () => {
        if (!this.containerData.isClipboardEmpty()) {
          const cells = this.containerData.paste({ offset: 32 })
          this.containerData.cleanSelection()
          this.containerData.select(cells)
        }
        return false
      })
      this.containerData.bindKey('ctrl+z', () => {
        if(this.canUndo){
          this.containerData.undo()
        }
      })
      this.containerData.bindKey('ctrl+b', () => {
        if(this.canRedo){
          this.containerData.redo()
        }
      })
      this.containerData.bindKey('backspace', () => {
        const cells = this.containerData.getSelectedCells()
        if (cells.length !== 0) {
          this.containerData.removeCells(cells)
        }
      })
    },
    //导入数据
    loadData(){
      this.dealSVG()
      this.stencilData.load(this.iconData, 'group1')
    },
    //保存数据
    save(){
      console.log(this.containerData.toJSON())
    },
    //与右侧双向绑定
    getRightData(selectSvgInfo){
      this.selectSvgInfo = selectSvgInfo
    },
    //右侧点击添加table
    addTable(node){
      let NodeX = node.store.data.position.x
      let Width = node.store.data.size.width + 15
      let NodeY = node.store.data.position.y
      node.addChild(this.containerData.addNode({
        shape: 'table',
        x: NodeX + Width,
        y: NodeY,
        data: {
          tableData: [
            {
              key: '数据名',
              value: '数据',
              isEditor: false
            },
            {
              key: '数据名',
              value: '数据',
              isEditor: false
            },
            {
              key: '数据名',
              value: '数据',
              isEditor: false
            },
            {
              key: '数据名',
              value: '数据',
              isEditor: false
            },
          ],
        }
      }))
      node.store.data.tableId = node.getChildren()[0].id
    },
    //预览
    handlePreviewOperation(){
      localStorage.setItem("svgInfo", JSON.stringify(this.containerData.toJSON()));
      this.$router.push({
        path: "/tuopuPreview",
        name: "tuopuPreview",
      })
    },
    dealSVG() {
      axios.get("InterfaceReturn.json").then((res) => {
        if (res.data !== null && res.data.length > 0) {
          const dataList = res.data;
          let portList = {
            groups: {
              topRect: {
                position: 'top',
                attrs: {
                  circle: {
                    r: 5,
                    magnet: true,
                    stroke: '#31d0c6',
                    fill: '#fff',
                    strokeWidth: 1,
                  }
                }
              },
              leftRect: {
                position: 'left',
                attrs: {
                  circle: {
                    r: 5,
                    magnet: true,
                    stroke: '#31d0c6',
                    fill: '#fff',
                    strokeWidth: 1,
                  }
                }
              },
              rightRect: {
                position: 'right',
                attrs: {
                  circle: {
                    r: 5,
                    magnet: true,
                    stroke: '#31d0c6',
                    fill: '#fff',
                    strokeWidth: 1,
                  }
                }
              },
              bottomRect: {
                position: 'bottom',
                attrs: {
                  circle: {
                    r: 5,
                    magnet: true,
                    stroke: '#31d0c6',
                    fill: '#fff',
                    strokeWidth: 1,
                  }
                }
              },
            },
            items:[
              { id: 'topRect', group: 'topRect'},
              { id: 'leftRect', group: 'leftRect'},
              { id: 'rightRect', group: 'rightRect'},
              { id: 'bottomRect', group: 'bottomRect'},
            ]
          }
          let str = `<svg t="1691115252136" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2277" width="200" height="200"><path d="M287.182961 232.446353l449.559767 0 0 134.82582-449.559767 0 0-134.82582Z" fill="#EEE82C" p-id="2278"></path><path d="M669.317432 404.725166h-314.709176a104.878288 104.878288 0 0 1 0-209.756577h314.709176a104.878288 104.878288 0 1 1 0 209.756577z m-314.709176-134.82582a29.953725 29.953725 0 0 0 0 59.907449h314.709176a29.953725 29.953725 0 1 0 0-59.907449z" fill="#74B65B" p-id="2279"></path><path d="M521.189855 1024a37.601616 37.601616 0 0 1-13.363684-2.47705L192.411035 901.026863C181.487246 897.311288 74.899793 858.347295 74.899793 773.458798V222.637236c0-0.705959 0-1.684394 0.123853-2.73714s-0.123852-2.018796-0.123853-3.046772C74.899793 93.223769 262.808791 0 512.02477 0s437.075436 93.223769 437.075437 216.853324c0 0.805041 0 1.808246-0.123853 2.823837s0.123852 1.857787 0.123853 2.947689V773.458798c0 66.731721-76.999093 111.591093-92.443499 119.876825a33.898426 33.898426 0 0 1-3.926123 1.857788L535.024178 1021.361942a37.638772 37.638772 0 0 1-13.834323 2.638058zM149.830549 224.3464V773.458798c0 23.87876 44.339191 48.971274 68.11887 57.120769l303.005116 115.752537 301.878059-119.901596c24.535178-13.859094 51.312087-39.001149 51.312086-52.97171V224.58172c-0.123852-1.127058-0.222934-2.21696-0.272475-3.319247v-2.761911c0-0.928894 0.123852-2.21696 0.247705-3.49264-2.811452-66.496402-156.760096-140.077166-362.09514-140.077166S152.629616 148.51152 149.88009 215.020307c0.123852 1.176599 0.198164 2.340812 0.222935 3.492641a50.197414 50.197414 0 0 1-0.272476 5.833452z" fill="#74B65B" p-id="2280"></path><path d="M711.774066 666.140616H312.164008a37.465378 37.465378 0 0 1 0-74.930756h399.610058a37.465378 37.465378 0 1 1 0 74.930756z" fill="#74B65B" p-id="2281"></path></svg>`
          dataList.forEach((item) => {
            const componentInfo = {
              template: str, // 使用提取的 SVG 内容作为组件的模板
            };
            const vom = Vue.component(item.type, componentInfo);
            register({
              shape: 'svgNode',
              width: 50,
              height: 50,
              component: vom,
              ports: portList,
            });
            const svg = this.containerData.createNode({
              shape: 'svgNode',
              x: 100,
              y: 60,
            });
            this.iconData.push(svg);
          });
        }
      });
    }
  },
  mounted() {
    this.init()
  },
  created() {
  },
  computed:{
    showSidebar(){
      return this.$store.getters.showSidebar
    },
    iconData(){
      return initAntVNode()
    }
  },
  watch:{
    'showSidebar':{
      immediate:true,
      handler(){
        if (this.number%2 === 1){
          this.width = '11.9rem'
        }else {
          this.width = '10.5rem'
        }
        this.number++
      },
    },
  }
};
</script>

<style scoped lang="less">
#index{
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: row;
  background: #1C2961;
  .leftContain{
    background:white;
    width: max-content;
    height: 100%;
    #stencilContainer{
      width: 3rem;
      height: 100%;

      ::v-deep .searchable {
        width: 3rem;
        height: 100%;
      }
    }
  }
  .centerContain{
    height: 100%;
    display: flex;
    flex-direction: column;
    .header{
      border-bottom: #16214d 3px solid;
      height: 5%;
      button{
        margin-left: 0.3rem;
        margin-top: 0.05rem;
        width: 1rem;
        height: 0.4rem;
        padding-bottom: 0;
        padding-top: 0;
      }
    }
    #container{
      background: black;
      height: 95%;
    }
  }

  .rightContain{
    border-left: #16214d 3px solid;
    width: 4rem;
    height: 100%;
  }
}
/deep/ .x6-widget-transform-rotate{
  width: 0.2rem;
  height: 0.2rem;
  left: 37%;
  cursor:pointer;
  background: black url("../../assets/images/rotate.png");
  background-size: cover;
}
/deep/ .x6-port{
  visibility: hidden;
}

/deep/ .x6-widget-transform {
  border: 2px dashed #e7e2e2;
}

/deep/ .x6-cell rect{
  visibility: hidden;
}

/deep/ .foreignObject{
  visibility: visible;
}
</style>
